﻿//#define USE_WINMM_WIN32
#define USE_HIGH_RESOL
//#define USE_UGLY_PORTABLE // <- :P


using System.Collections.Generic;
using System.Runtime.InteropServices;
using HAVNet.Core.Lambda;

#if USE_HIGH_RESOL
using System.Diagnostics;
#endif

namespace HAVNet.Core.Time
{
    public class Crono
    {
        #if USE_WINMM_WIN32
        [DllImport("winmm.dll")]
        static extern uint timeGetTime ();
        #endif

        #if USE_HIGH_RESOL
        static Stopwatch swatch = new Stopwatch();
        #endif

        public static int milis ()
        {
            #if USEWINMM
            return (int) timeGetTime ();
            #endif

            #if USE_UGLY_PORTABLE
            return Environment.TickCount;
            #endif

            #if USE_HIGH_RESOL
            if (swatch.IsRunning) {
                swatch.Stop();
                return (int) swatch.ElapsedMilliseconds;
            }
            else {
                swatch.Reset();
                swatch.Start();
                return 0;
            }
            #endif
        }

        public static int getActionMilis (VFunc action)
        {
            return getActionTime (action, milis);
        }
        
        public static int getActionTime (VFunc action, Func<int> timeProvider)
        {
            int start   = timeProvider ();
            action      ();
            int end     = timeProvider();

            return end - start;
        }

        public static void showActionTime(string name, VFunc action, VFunc<string> header, VFunc<string/*nombre*/, int/*tiempo*/> footer, Func<int/*tiempo*/> timeProvider)
        {
            header (name);
            footer (name, getActionTime (action, timeProvider));
        }

        public static void showActionTime(string name, VFunc action, VFunc<string/*nombre*/, int/*tiempo*/> footer, Func<int/*tiempo*/> timeProvider)
        {
            footer (name, getActionTime (action, timeProvider));
        }

        public static void showActionMilis(string name, VFunc action, VFunc<string> header, VFunc<string/*nombre*/, int/*tiempo*/> footer)
        {
            header(name);
            footer(name, getActionTime(action, milis));
        }

        public static void showActionMilis (string name, VFunc action, VFunc<string/*nombre*/, int/*tiempo*/> footer)
        {
            footer (name, getActionTime (action, milis));
        }
    }
}
